<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>类和构造函数</title>
</head>

<body>
  <script>
    // 这是用来初始化新range对象的构造函数
    // 注意它不创建或返回对象，只初始化this
    function Range(from, to) {
      // 保存新范围对象的起点和终点（状态）
      // 这些属性不是继承，而是当前对象独有的属性
      console.log(this);
      this.from = from
      this.to = to
      console.log(new.target);
    }

    // 所有Range对象都继承这个对象，这个属性必须命名为prototype才行
    Range.prototype = {
      // 如果x在范围内则返回true，否则返回false
      // 这个方法适用于文本、日期和数值范围
      // includes: function (x) { return this.from <= x && x <= this.to },
      // 这个生成器函数让这个类的实例可迭代
      // 注意：只适用于数值范围
      [Symbol.iterator]: function* () {
        for (let x = Math.ceil(this.from); x <= this.to; x++)yield x;
      },
      // 返回范围的字符串表示
      // toString() { return "(" + this.from + "..." + this.to + ")" },
      // constructor: Range
    }
    Range.prototype.constructor = Range
    Range.prototype.includes = function (x) { return this.from <= x && x <= this.to }
    Range.prototype.toString = function (x) { return "(" + this.from + "..." + this.to + ")" }

    // 以下是使用这个新range类的示例
    let a = new Range(1, 3)
    // console.log(Range);
    console.log(a);
    console.log(a.includes(3));
    console.log(a.toString());
    console.log([...a]);
    console.log(a.constructor);

    // 9.2.1构造函数、类标识和instanceof
    // 使用instanceof操作符测试类的成员关系，构造函数是其有操作数
    console.log(a instanceof Range);//true a继承了Range.prototype
    function Strange() { }
    Strange.prototype = Range.prototype
    console.log(new Strange() instanceof Range);//true
    // 如果定义类时没有使用构造函数，是无法对这个类使用instanceof操作符，我们可以用isPrototypeOf（）方法检测对象是不是无构造函数类的成员，见类和原型例子

    // 9.2.2 constructor属性
    let F = function () { 1 }
    let p = F.prototype
    let c = p.constructor
    console.log(F);
    console.log(p);
    console.log(c);
    console.log(c === F);
  </script>
</body>

</html>